/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tuplestoreclient;

import core.IServerCallBack;
import core.ProtocolSD;
import core.ProtocolSD.Operation;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.charset.Charset;

/**
 *
 * @author Jorge
 */
public class ClienteListener implements ProtocolSD.IProtocolListener {

    /** ocurrente operação */
    private Operation operation;
    /** callback responsabel por propagar eventos*/
    private IServerCallBack callback;
    /** flag de finalização de pedido*/
    private boolean close=false;

    public void onReadHeader(int operation, int numArgs, ProtocolSD protocolSD) {
        this.operation = Operation.values()[operation];
        callback.onReadHeader(operation, numArgs, protocolSD);
    }
    

    public void onReadArgument(byte[] data, ProtocolSD protocolSD) {
        switch (operation) {
            case REDIRECT_READ:
                handleRedirectRead(data);
                break;
            case REDIRECT_WRITE:
                handleRedirectWrite(data);
                break;
            case DATA : handleData(data);
            break;
        }
        callback.onReadArgument(data, protocolSD);
    }

    public void handleRedirectRead(byte[] data) {
        ByteBuffer bb = ByteBuffer.allocate(data.length + 1);
        bb.put(data);
        bb.flip();
        Url url = Url.parse(Charset.defaultCharset().decode(bb).toString());
        callback.onNewResult(url.getKey(), url);
    }

    public void handleRedirectWrite(byte[] data) {
        ByteBuffer bb = ByteBuffer.allocate(data.length + 1);
        bb.put(data);
        bb.flip();
        Url url = Url.parse(Charset.defaultCharset().decode(bb).toString());
        callback.onNewResult(url.getKey(), url);
    }

    public void handleData(byte[] data) {
        // TODO : ver se passa por aqui
        int key = ProtocolSD.byteArrayToInt(data, 0);
        if(data.length==4){
            callback.onNewResult(key,null);
        }else{
            callback.onNewResult(key, ProtocolSD.subArray(data,4, data.length));
        }
    }

    public void onReadArgumentSize(int size, ProtocolSD protocolSD) {
        callback.onReadArgumentSize(size, protocolSD);
    }

    public void onReadAllArguments(ProtocolSD protocolSD) {
        //Desliga-se após ter lido tudo (comportamento por default)
        protocolSD.getKey().interestOps(SelectionKey.OP_WRITE); //coloca-se em modo de escrita
        close=true;
        try {
            protocolSD.close();
        } catch (IOException exception) {
            exception.printStackTrace();
        }
        callback.onFinish();
        callback.onReadAllArguments(protocolSD);
    }

    public void setCallBack(IServerCallBack callback) {
        this.callback = callback;
    }

    public IServerCallBack getCallBack() {
        return callback;
    }

    public void onWriteComplete(ProtocolSD protocolSD) {
        //Após ter escrito tudo coloca-se á espera de ler
        protocolSD.getKey().interestOps(SelectionKey.OP_READ);
        callback.onWriteComplete(protocolSD);
    }

    public void onAcceptConnect() {
        //invocado após conecção com servidor
        callback.onFinishConnect();
    }

    public void onReadParcialParam(byte[] readedBytes, int tmpParcial, int remaning,ProtocolSD protocolSD) {
        callback.onReadParcialParam(readedBytes, tmpParcial, remaning);
    }

    public boolean isClose() {
        return close;
    }

}
